package com.itbaizhan.myorder;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*延迟队列，即消息进入队列后不会立即被消费，只有到达指定时间后，才会被消费。

例如：用户下单后，30分钟后查询订单状态，未支付则会取消订单。
    但RabbitMQ中并未提供延迟队列功能，我们可以使用死信队列实现延迟队列的效果。*/
@Configuration
public class RabbitConfig {
    //订单交换机和队列
    private final String ORDER_EXCHANGE = "order_exchange";
    private final String ORDER_QUEUE = "order_queue";
    //过期订单交换机和队列（死信交换机和队列）
    private final String EXPIRE_EXCHANGE = "expire_exchange";
    private final String EXPIRE_QUEUE = "expire_queue";

    //过期订单交换机
    @Bean(EXPIRE_EXCHANGE)
    public Exchange expireExchange(){
        return ExchangeBuilder
                .topicExchange(EXPIRE_EXCHANGE)
                .durable(true)
                .build();
    }
    //过期订单队列
    @Bean(EXPIRE_QUEUE)
    public Queue expirQueue(){
        return QueueBuilder
                .durable(EXPIRE_QUEUE)
                .build();
    }
    //过期订单队列绑定到交换机
    @Bean
    public Binding bindExpireQueue(@Qualifier(EXPIRE_EXCHANGE)Exchange exchange, @Qualifier(EXPIRE_QUEUE)Queue queue){
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("expire_routing")
                .noargs();
    }
    //订单交换机
    @Bean(ORDER_EXCHANGE)
    public Exchange orderExchange(){
        return ExchangeBuilder
                .topicExchange(ORDER_EXCHANGE)
                .durable(true)
                .build();
    }
    //订单队列
    @Bean(ORDER_QUEUE)
    public Queue orderQueue(){
        return QueueBuilder
                .durable(ORDER_QUEUE)
                .deadLetterExchange(EXPIRE_EXCHANGE) //死信交换机
                .deadLetterRoutingKey("expire_routing")  //死信路路关键字
                .ttl(10000)  //存活10秒  模拟存活30分钟
                .build();
    }
    //订单队列绑定到交换机
    @Bean
    public Binding bindOrderQueue(@Qualifier(ORDER_EXCHANGE)Exchange exchange, @Qualifier(ORDER_QUEUE)Queue queue){
        return BindingBuilder
                .bind(queue)
                .to(exchange)
                .with("order_routing")
                .noargs();
    }
}
/*用列信交换机有一个缺点：
* RabbitMQ只会移除队列顶端的过期消息，如果第一个消息的存活时长较长，
* 而第二个消息的存活时长较短，则第二个消息并不会及时执行。*/